package kz.kstu.scantest.desktop.ui.frame;

import kz.kstu.scantest.app.delegate.api.FormDataDelegate;
import kz.kstu.scantest.app.delegate.api.TestDelegate;
import kz.kstu.scantest.app.delegate.impl.FormDataDelegateImpl;
import kz.kstu.scantest.app.delegate.impl.TestDelegateImpl;
import kz.kstu.scantest.business.client.excel.TestExcelImporter;
import kz.kstu.scantest.business.client.excel.TestResultExcelExporter;
import kz.kstu.scantest.business.common.exception.LogicException;
import kz.kstu.scantest.business.entity.data.FormData;
import kz.kstu.scantest.business.entity.security.Account;
import kz.kstu.scantest.business.entity.test.Test;
import kz.kstu.scantest.business.util.StringUtil;
import kz.kstu.scantest.desktop.report.AbstractFormDataReport;
import kz.kstu.scantest.desktop.report.FormDataReportEnum;
import kz.kstu.scantest.desktop.ui.dialog.LoginDialog;
import kz.kstu.scantest.desktop.ui.dialog.ProgressDialog;
import kz.kstu.scantest.desktop.ui.dialog.ReportTypeDialog;
import kz.kstu.scantest.desktop.ui.dialog.SchoolGuide;
import kz.kstu.scantest.desktop.ui.page.ScanPage;
import kz.kstu.scantest.desktop.util.GUIUtils;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.view.JasperViewer;
import org.apache.log4j.Logger;

import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.List;

/**
 * @author Filipp_Stankevich
 *         created: 25.07.11 20:40
 */
public class ApplicationFrame extends JFrame {

    private final static Logger LOGGER = Logger.getLogger(ApplicationFrame.class);

    private static final String EXCEL_EXTENSION = ".xls";

    private static final String GUIDES_MENU = "Справочники";
    private static final String SCHOOLS_MENU_ITEM = "Школы";
    private static final String SERVICE_MENU = "Сервис";
    private static final String REPORTS_MENU = "Отчеты";
    private static final String EXCEL_EXPORT = "Экспорт в Excel";
    private static final String QUESTION_IMPORT = "Импорт вопросов";
    private static final String ANALYZE_ANSWERS_REPORT = "Карта анализа ответов";
    private static final String ANSWERS_REPORT = "Ведомость";
    private static final String TITLE = "Scantest";
    private static final String REPORT_ERROR = "Ошибка в файле отчета";
    private static final String CAN_NOT_SAVE_FILE = "Файл не может быть записан.";
    private static final String EXPORT_SUCCESSFULLY_FINISHED = "Экспорт успешно завершен.";
    private static final String STATISTIC = "Показать статистику";
    private static final String CHANGE_STATISTIC = "Изменить статистику";
    private static final String STATISTIC_TITLE = "Статистика";
    private static final String STATISTIC_VALUE_REQUEST = "Введите числовое значение:";
    private static final String INCORRECT_VALUE = "Введенное значение некорректно";
    private static final String STATISTIC_WAS_SUCCESSFULLY_CHANGED = "Статискика успешна изменена";
    private static final String ERROR_TITLE = "Ошибка";
    private static final String QUESTIONS_WAS_SUCCESSFULY_PROCESSED = "Вопросы успешно импортированы";

    private JMenuItem schoolGuideMenuItem;
    private JMenuItem questionImportMenuItem;
    private JMenuItem analyzeAnswerReportMenuItem;
    private JMenuItem answerReportMenuItem;
    private JMenuItem statisticMenuItem;
    private JMenuItem changeStatisticMenuItem;
    private JMenuItem excelExportMenuItem;

    private ScanPage scanPage = new ScanPage();
    private FormDataDelegate formDataDelegate = new FormDataDelegateImpl();

    public void initStaticComponents() {
        initMenuBar();
        initListeners();
        initWindow();

        scanPage.initializeStaticComponents();
        setContentPane(scanPage.getRootPanel());
    }

    public void initData() {
        scanPage.initData();
    }

    private void initMenuBar() {
        JMenuBar menuBar = new JMenuBar();

        JMenu guidesMenu = new JMenu(GUIDES_MENU);
        schoolGuideMenuItem = new JMenuItem(SCHOOLS_MENU_ITEM);
        guidesMenu.add(schoolGuideMenuItem);

        JMenu reportMenu = new JMenu(REPORTS_MENU);
        analyzeAnswerReportMenuItem = new JMenuItem(ANALYZE_ANSWERS_REPORT);
        reportMenu.add(analyzeAnswerReportMenuItem);
        answerReportMenuItem = new JMenuItem(ANSWERS_REPORT);
        reportMenu.add(answerReportMenuItem);
        excelExportMenuItem = new JMenuItem(EXCEL_EXPORT);
        reportMenu.add(excelExportMenuItem);

        JMenu serviceMenu = new JMenu(SERVICE_MENU);
        questionImportMenuItem = new JMenuItem(QUESTION_IMPORT);
        serviceMenu.add(questionImportMenuItem);
        statisticMenuItem = new JMenuItem(STATISTIC);
        serviceMenu.add(statisticMenuItem);
        changeStatisticMenuItem = new JMenuItem(CHANGE_STATISTIC);
        serviceMenu.add(changeStatisticMenuItem);
        //changeStatisticMenuItem.setVisible(ClientContext.getInstance().isAdmin());

        menuBar.add(reportMenu);
        menuBar.add(guidesMenu);
        menuBar.add(serviceMenu);
        this.setJMenuBar(menuBar);
    }

    private void initWindow() {
        this.setTitle(TITLE);
        this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        this.setResizable(false);
        this.setSize(GUIUtils.preferredStartupScreenSize());
        this.setMinimumSize(GUIUtils.preferredStartupScreenSize());
    }

    private void initListeners() {
        final JFrame instance = this;

        schoolGuideMenuItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                SchoolGuide schoolGuide = new SchoolGuide();
                schoolGuide.initStaticComponents();
                schoolGuide.initData();
                GUIUtils.centerAndShow(schoolGuide);
                scanPage.updateSchools();
            }
        });

        questionImportMenuItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JFileChooser fileChooser = new JFileChooser();
                fileChooser.setFileFilter(new ExcelFileFilter());
                int state = fileChooser.showOpenDialog(instance);
                if (state == JFileChooser.APPROVE_OPTION) {
                    final ProgressDialog dialog = new ProgressDialog();
                    final File file = fileChooser.getSelectedFile();
                    final Thread thread = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                TestExcelImporter importer = new TestExcelImporter();
                                Collection<Test> tests = importer.process(file);
                                TestDelegate testDelegate = new TestDelegateImpl();
                                testDelegate.saveTests(tests);
                                JOptionPane.showMessageDialog(instance, QUESTIONS_WAS_SUCCESSFULY_PROCESSED, TITLE, JOptionPane.INFORMATION_MESSAGE);
                            } catch (LogicException ex) {
                                JOptionPane.showMessageDialog(instance, ex.getMessage(), ERROR_TITLE, JOptionPane.ERROR_MESSAGE);
                            } catch (IOException ex) {
                                JOptionPane.showMessageDialog(instance, ex.getMessage(), ERROR_TITLE, JOptionPane.ERROR_MESSAGE);
                            } finally {
                                SwingUtilities.invokeLater(new Runnable() {
                                    @Override
                                    public void run() {
                                        dialog.dispose();
                                    }
                                });
                            }
                        }
                    });
                    thread.start();
                    dialog.initStaticComponents();
                }
            }
        });

        analyzeAnswerReportMenuItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                buildAndShowReport(FormDataReportEnum.ANALYZE_REPORT);
            }
        });

        answerReportMenuItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                buildAndShowReport(FormDataReportEnum.ANSWER_REPORT);
            }
        });

        statisticMenuItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Integer count = formDataDelegate.getProcessedFormDataCount();
                JOptionPane.showMessageDialog(instance, count, STATISTIC_TITLE, JOptionPane.INFORMATION_MESSAGE);
            }
        });

        excelExportMenuItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                List<FormData> formDataList = getFormDataList();
                if (formDataList != null) {
                    JFileChooser fileChooser = new JFileChooser();
                    fileChooser.setFileFilter(new ExcelFileFilter());
                    int dialogResult = fileChooser.showSaveDialog(instance);
                    if (dialogResult == JFileChooser.APPROVE_OPTION) {
                        TestResultExcelExporter exporter = new TestResultExcelExporter();
                        File file = fileChooser.getSelectedFile();
                        String filePath = file.getPath();
                        if (!filePath.endsWith(EXCEL_EXTENSION)) {
                            filePath = filePath + EXCEL_EXTENSION;
                        }
                        try {
                            exporter.export(filePath, formDataList);
                            JOptionPane.showMessageDialog(instance, EXPORT_SUCCESSFULLY_FINISHED, TITLE, JOptionPane.INFORMATION_MESSAGE);
                        } catch (IOException ex) {
                            LOGGER.error(ex.getMessage(), ex);
                            JOptionPane.showMessageDialog(instance, CAN_NOT_SAVE_FILE, TITLE, JOptionPane.ERROR_MESSAGE);
                        }
                    }
                }
            }
        });

        changeStatisticMenuItem.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                LoginDialog loginDialog = new LoginDialog();
                Account account = loginDialog.login();
                if (account != null) {
                    String value = JOptionPane.showInputDialog(instance, STATISTIC_VALUE_REQUEST, STATISTIC_TITLE, JOptionPane.QUESTION_MESSAGE);
                    if (value != null) {
                        if (value.length() > 0 && StringUtil.isNumber(value)) {
                            formDataDelegate.changeStatistic(Integer.parseInt(value));
                            JOptionPane.showMessageDialog(instance, STATISTIC_WAS_SUCCESSFULLY_CHANGED, STATISTIC_TITLE, JOptionPane.INFORMATION_MESSAGE);
                        } else {
                            JOptionPane.showMessageDialog(instance, INCORRECT_VALUE, STATISTIC_TITLE, JOptionPane.ERROR_MESSAGE);
                        }
                    }
                }
            }
        });
    }

    private void buildAndShowReport(FormDataReportEnum formDataReportEnum) {
        List<FormData> formDataList = getFormDataList();
        if (formDataList != null) {
            AbstractFormDataReport report = AbstractFormDataReport.getInstance(formDataReportEnum);
            try {
                JasperPrint jasperPrint = report.buildReport(formDataList);
                JasperViewer.viewReport(jasperPrint, false);
            } catch (JRException ex) {
                LOGGER.error(ex.getMessage(), ex);
                JOptionPane.showMessageDialog(this, REPORT_ERROR, TITLE, JOptionPane.ERROR_MESSAGE);
            }
        }
    }

    private List<FormData> getFormDataList() {
        ReportTypeDialog dialog = new ReportTypeDialog();
        dialog.initStaticComponent();
        List<FormData> formDataList = null;
        if (!dialog.isCanceled()) {
            if (dialog.getReportType() == ReportTypeDialog.ALL) {
                formDataList = scanPage.getFormDataList();
            } else {
                formDataList = scanPage.getSelectedFormDataList();
            }
        }
        return formDataList;
    }

    private class ExcelFileFilter extends FileFilter {


        private static final String EXCEL_FILES_MESSAGE = "Файлы excel (*.xls)";

        @Override
        public boolean accept(File f) {
            String path = f.getPath();
            return f.isDirectory() || path.endsWith(EXCEL_EXTENSION)
                    || path.endsWith(EXCEL_EXTENSION.toUpperCase()) ;
        }

        @Override
        public String getDescription() {
            return EXCEL_FILES_MESSAGE;
        }
    }
}
